#include "stdafx.h"
#include "Scene.h"
#include "RenderObject.h"
#include "texture.h"

CScene::CScene()
{
    Initialize();
}

CScene::~CScene()
{

}

void CScene::Initialize()
{
    ResetRenderObjs();
}


void CScene::Render()
{
    for( RenderMap::iterator iter = m_renderObjs.begin(); iter != m_renderObjs.end(); iter++ )
    {
        RenderLayerVec &v = iter->second;
        int rendertype = 0;
        for( RenderLayerVec::iterator iterV = v.begin(); iterV != v.end(); iterV++ )
        {
            RenderObjVec &objs = *iterV;
            BeginRender( rendertype );

            for( RenderObjVec::iterator iterO = objs.begin(); iterO != objs.end(); iterO++ )
            {
                CRenderObject *pObj = *iterO;
                pObj->Render();
            }

            EndRender( rendertype );
            objs.clear();
            rendertype++;
        }
    }
}

void CScene::ResetRenderObjs()
{
    for( RenderMap::iterator iter = m_renderObjs.begin(); iter != m_renderObjs.end(); iter++ )
    {
        RenderLayerVec &v = iter->second;
        for( RenderLayerVec::iterator iterV = v.begin(); iterV != v.end(); iterV++ )
        {
            RenderObjVec &objs = *iterV;
            objs.clear();
        }
    }
}

void CScene::AddRenderObject( CRenderObject *pObj )
{
    RenderLayerVec &v = GetLayerVec( pObj->GetPriority() );
    int renderType = pObj->GetRenderType();
    if( renderType < 0 || renderType >= eRender_Num )
        return;
    v[renderType].push_back( pObj );
}

RenderLayerVec & CScene::GetLayerVec( int layer )
{
    RenderMap::iterator iter = m_renderObjs.find( layer );
    if( iter != m_renderObjs.end() )
    {
        return iter->second;
    }
    else
    {
        g_log.WriteInfo( "Didn't find layer vec, creating one " );
        RenderLayerVec v;
        v.resize( eRender_Num );
        m_renderObjs.insert( std::make_pair( layer, v ) );
        return GetLayerVec( layer );
    }
}

void CScene::BeginRender( int rendertype )
{
    IDirect3DDevice9 *pDevice = CD3DManager::Instance().GetDevice();
    switch ( rendertype )
    {
    case eRender_AlphaTex_ColorDiff:
        {
            pDevice->SetTextureStageState(0, D3DTSS_COLOROP,  D3DTOP_SELECTARG1 );
            pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE );
            //pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
            //pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
            pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
            pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
            pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);

            pDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE );
            pDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );

            pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
            pDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
            pDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
        }
        break;

    case eRender_Texture:
        pDevice->SetTextureStageState(0, D3DTSS_COLOROP,  D3DTOP_SELECTARG1 );
        pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
        pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
        pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);

        pDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE );
        pDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );

        pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
        pDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
        pDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
        break;

    case eRender_Tex1All_Tex2Alpha:
        pDevice->SetTextureStageState(0, D3DTSS_COLOROP,  D3DTOP_SELECTARG1 );
        pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
        pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
        pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);

        pDevice->SetTextureStageState(1, D3DTSS_COLOROP,  D3DTOP_SELECTARG1 );
        pDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT );
        pDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
        pDevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);

        pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
        pDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
        pDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
        break;
    }
}

void CScene::EndRender( int rendertype )
{
    IDirect3DDevice9 *pDevice = CD3DManager::Instance().GetDevice();
    pDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE );
    pDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
}
